package studentmsg

import (
	"errors"
)

// MsgList 是用于存放多个StudentMsg结构体的线性表
type MsgList struct {
	head   *StudentMsg
	tail   *StudentMsg
	length int
}

// Init 用于初始化线性表MsgList
func (l *MsgList) Init() {
	l.head = nil
	l.tail = nil
	l.length = 0
}

// insert 用于在线性表中插入一个StudentMsg元素
// location 的值为 0~length
// return 表示插入是否成功
func (l *MsgList) insert(location int, s *StudentMsg) bool {
	newOne := s.copy()
	if location == 0 {
		if l.length == 0 {
			l.head = newOne
			l.tail = newOne
		} else {
			head := l.head
			head.previous = newOne
			newOne.next = head
			l.head = newOne
		}
		l.length++
		return true
	} else if location == l.length {
		tail := l.tail
		tail.next = newOne
		newOne.previous = tail
		l.tail = newOne
		l.length++
		return true
	} else if location > 0 && location < l.length {
		now := l.head
		for i := 1; i < location; i++ {
			now = now.next
		}
		nextOfNow := now.next
		now.next = newOne
		nextOfNow.previous = newOne
		newOne.previous = now
		newOne.next = nextOfNow
		l.length++
		return true
	} else {
		return false
	}
}

// delete 用于从MsgList中删除一个元素
// location 表示需要删除的元素所在位置
// return 返回从MsgList中删除的元素，若返回nil表示删除失败
func (l *MsgList) delete(location int) *StudentMsg {
	if l.length == 0 {
		return nil
	} else if location == 0 {
		head := l.head
		if l.length == 1 {
			l.head = nil
			l.tail = nil
		} else {
			nextOfHead := head.next
			nextOfHead.previous = nil
			l.head = nextOfHead
		}
		head.next = nil
		head.previous = nil
		l.length--
		return head
	} else if location == l.length-1 {
		tail := l.tail
		previousOfTail := tail.previous
		tail.previous = nil
		tail.next = nil
		previousOfTail.next = nil
		l.tail = previousOfTail
		l.length--
		return tail
	} else if location > 0 && location < l.length-1 {
		now := l.head
		for i := 0; i < location; i++ {
			now = now.next
		}
		previousOfNow := now.previous
		nextOfNow := now.next
		previousOfNow.next = nextOfNow
		nextOfNow.previous = previousOfNow
		now.next = nil
		now.previous = nil
		l.length--
		return now
	} else {
		return nil
	}
}

// search is used to search student rely on student's name or id
// return students's index in MsgList
func (l *MsgList) search(name string, id string) ([]int, error) {
	var students []int
	if name == "" && id == "" {
		return students, errors.New("name and id should not both be null")
	}
	now := l.head
	for i := 0; i < l.length; i++ {
		if (name == "" || name != "" && name == now.name) && (id == "" || id != "" && id == now.id) {
			students = append(students, i)
		}
		now = now.next
	}
	return students, nil
}

// getStudent is used to get student base on student's location in MsgList
func (l *MsgList) getStudent(location int) *StudentMsg {
	now := l.head
	for i := 0; i < location; i++ {
		now = now.next
	}
	return now.copy()
}

// getAll is used to get all students message
func (l *MsgList) getAll() []StudentMsg {
	var students []StudentMsg
	now := l.head
	for i := 0; i < l.length; i++ {
		students = append(students, *now.copy())
		now = now.next
	}
	return students
}
